using System;
using System.Collections.Generic;
using System.Text;
//using AlgorithmsVisualized.Controls;
using GraphConstructor;
using AlgorithmsVisualized.Components;

namespace KruskalDemo
{
    [VisualAlgorithm]
    public class Kruskal : IGraph
    {
        internal class KruskalEnumerated : IEnumerator<IStep>
        {
            SortedDictionary<Edge, Edge> Q;
            Kruskal g;
            Edge edge;
            IStep step;
            int i;

            public IStep Current
            {
                get { return step; }
            }

            public void Dispose()
            {

            }

            object System.Collections.IEnumerator.Current
            {
                get { return step; }
            }

            public bool MoveNext()
            {
                if (Q == null || Q.Count == 0)
                    return false;
                #region
                /*
                if (i >= edge.Adj.Count)
                {
                    foreach (Node Key in Q.Keys)
                    {
                        edge = Key;
                        break;
                    }

                    Q.Remove(edge);
                    i = 0;
                }
                if (edge.Adj.Count <= 0)
                    return true;
                Edge d = edge.Adj[i];
                if (d.NodeTo.Value > edge.Value + d.Weight)
                {
                    Q.Remove(d.NodeTo);
                    step.State.Edges.Remove(new Edge(d.NodeTo.ID + edge.ID, 0));
                    d.NodeTo.Parent = edge;
                    d.NodeTo.Value = edge.Value + d.Weight;

                    Q.Add(d.NodeTo, null);

                    step.State.Nodes.Add(d.NodeTo);
                    step.State.Edges.Add(d);
                }
                */
                #endregion
                if (!Cicle(edge))
                {
                    Parent(edge.NodeTo).Parent = edge.NodeFrom;
                    step.State.Edges.Add(edge);
                }

                foreach (Edge Key in Q.Keys)
                {
                    edge = Key;
                    break;
                }
                Q.Remove(edge);
                i++;
                return true;
            }

            private bool Cicle(Edge edge)
            {
                if (Parent(edge.NodeFrom) == Parent(edge.NodeTo))
                    return true;
                return false;
            }

            private Node Parent(Node node)
            {
                if (node.Parent == null)
                    return node;
                return Parent(node.Parent);
            }
            public void Reset()
            {
                step = new KruskalStep();
                step.State = new Kruskal();
                Q = new SortedDictionary<Edge, Edge>();
                foreach (Node n in g.Nodes)
                {
                    n.Parent = null;
                    step.State.Nodes.Add(n);
                }
                foreach (Edge edge in g.Edges)
                {
                    //step.State.Edges.Add(edge);
                    Q.Add(edge, null);
                }
                foreach (Edge Key in Q.Keys)
                {
                    edge = Key;
                    break;
                }

                Q.Remove(this.edge);
                i = 0;
            }

            public KruskalEnumerated(Kruskal d)
            {
                g = d;
            }
        }
        internal class KruskalStep : IStep
        {
            private bool _isFinal;
            private IGraph _state;

            public IGraph State
            {
                get { return _state; }
                set { _state = value; }
            }
            public bool IsFinal
            {
                get { return _isFinal; }
                set { _isFinal = value; }
            }
        }
        private List<Edge> _edges = new List<Edge>();
        private List<Node> _nodes = new List<Node>();
        private List<Node> _startNodes = new List<Node>();

        #region IGraph Members

        public bool IsWeighted
        {
            get
            {
                return true;
            }
            set
            {
            }
        }

        public bool IsDirected
        {
            get
            {
                return false;
            }
            set
            {
            }
        }

        public List<Edge> Edges
        {
            get { return _edges; }
            set { _edges = value; }
        }
        public List<Node> Nodes
        {
            get { return _nodes; }
            set { _nodes = value; }
        }
        public List<Node> StartNodes
        {
            get
            {
                return _startNodes;
            }
            set
            {
                _startNodes = value;
            }
        }
        #endregion

        public IEnumerator<IStep> GetEnumerator()
        {
            return new KruskalEnumerated(this);
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #region IGraph Members

        public string Name
        {
            get
            {
                return "Dijkstra";
            }
        }

        public string Description
        {
            get
            {
                return "Dijkstra algorithm loops on every node, then trys to relax this node by updating its neighabours (if applicable)";
            }
        }
        public string Complexty
        {
            get
            {
                return "v.lgE";
            }
        }
        #endregion
    }
}
